package org.jc.auth.domain.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import com.google.gson.Gson;
import jakarta.annotation.Resource;
import org.jc.auth.common.enums.IsDeletedFlagEnum;
import org.jc.auth.common.redis.RedisUtil;
import org.jc.auth.common.util.PasswordEncoderUtil;
import org.jc.auth.domain.constants.AuthConstant;
import org.jc.auth.domain.convert.AuthRoleBOConverter;
import org.jc.auth.domain.convert.AuthUserBOConverter;
import org.jc.auth.domain.entity.AuthRoleBO;
import org.jc.auth.domain.entity.AuthUserBO;
import org.jc.auth.domain.service.AuthUserDomainService;
import org.jc.auth.infra.basic.entity.AuthRole;
import org.jc.auth.infra.basic.entity.AuthUser;
import org.jc.auth.infra.basic.entity.AuthUserRole;
import org.jc.auth.infra.basic.service.AuthRoleService;
import org.jc.auth.infra.basic.service.AuthUserRoleService;
import org.jc.auth.infra.basic.service.AuthUserService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.stream.Collectors;

/**
 * 功能描述
 *
 * @author wanghongqian
 * @date 2024/07/12 17:27
 */
@Service
public class AuthUserDomainServiceImpl implements AuthUserDomainService {

    @Resource
    private AuthUserService authUserService;

    @Resource
    private AuthUserRoleService authUserRoleService;

    @Resource
    private AuthRoleService authRoleService;

    @Resource
    private RedisUtil redisUtil;

    private String authPermissionPrefix = "auth.permission";

    private String authRolePrefix = "auth.role";

    @Override
    @Transactional
    public Boolean register(AuthUserBO authUserBO) {
        AuthUser authUser = AuthUserBOConverter.INSTANCE.convertBOToEntity(authUserBO);
        authUser.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getCode());
        authUser.setPassword(PasswordEncoderUtil.encode(authUserBO.getPassword()));
        Integer count = authUserService.insert(authUser);

        // 建立一个初步的角色关联
        AuthRole authRole = new AuthRole();
        authRole.setRoleKey(AuthConstant.NORMAL_USER);
        AuthRole role = authRoleService.queryByCondition(authRole);

        AuthUserRole authUserRole = new AuthUserRole();
        authUserRole.setUserId(authUser.getId());
        authUserRole.setRoleId(role.getId());
        authUserRole.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getCode());
        authUserRoleService.insert(authUserRole);

        // 构建用户-角色 的缓存
        String roleKey = redisUtil.buildKey(authRolePrefix, authUser.getUserName());
        AuthUserRole userRoleCondition = new AuthUserRole();
        userRoleCondition.setUserId(authUser.getId());
        List<AuthUserRole> authUserRoles = authUserRoleService.queryByCondition(userRoleCondition);

        List<Long> authRoleIds = authUserRoles.stream().map(AuthUserRole::getRoleId).collect(Collectors.toList());
        List<AuthRole> authRoles = authRoleService.queryByIds(authRoleIds);
        List<AuthRoleBO> authRoleBOList = AuthRoleBOConverter.INSTANCE.convertEntityToBOList(authRoles);
        redisUtil.set(roleKey,new Gson().toJson(authRoleBOList));

        return count > 0;
    }

    @Override
    public Boolean delete(AuthUserBO authUserBO) {
        AuthUser authUser = new AuthUser();
        authUser.setId(authUserBO.getId());
        authUser.setIsDeleted(IsDeletedFlagEnum.DELETED.getCode());
        Integer count = authUserService.update(authUser);
        return count > 0;
    }

    @Override
    public Boolean update(AuthUserBO authUserBO) {
        AuthUser authUser = AuthUserBOConverter.INSTANCE.convertBOToEntity(authUserBO);
        Integer count = authUserService.update(authUser);
        return count > 0;
    }

    @Override
    public Boolean changeStatus(AuthUserBO authUserBO) {
        AuthUser authUser = new AuthUser();
        authUser.setId(authUserBO.getId());
        authUser.setStatus(authUserBO.getStatus());
        Integer count = authUserService.update(authUser);
        return count > 0;
    }

    @Override
    public void doLogin(AuthUserBO authUserBO) {
        AuthUser authUser = new AuthUser();
        authUser.setUserName(authUserBO.getUserName());
        List<AuthUser> authUserResultList = authUserService.queryByCondition(authUser);
        if(CollectionUtils.isEmpty(authUserResultList)){
            throw new RuntimeException("用户名或密码错误");
        }
        AuthUser authUserResult = authUserResultList.get(0);
        String passwordDb = authUserResult.getPassword();
        String password = authUserBO.getPassword();
        if(!PasswordEncoderUtil.check(password,passwordDb)){
            throw new RuntimeException("用户名或密码错误");
        }
        StpUtil.login(authUserBO.getUserName());
    }
}
